#include "server_thread.h"
#include "log_utils.h"
#include "database.h"

#include <unistd.h>
#include <cstring>
#include <iostream>
#include <sstream>
#include <vector>
#include <arpa/inet.h>
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QThread>
#include <QDebug>
#include <QFile>
#include <QDir>

std::vector<std::string> split_command(const std::string &input) {
    std::istringstream iss(input);
    std::vector<std::string> tokens;
    std::string s;
    while (iss >> s) tokens.push_back(s);
    return tokens;
}

QString getThreadConnectionName() {
    return QString("conn_%1").arg((quintptr)QThread::currentThreadId());
}

bool handle_upload(int sock, const std::string &filename, qint64 filesize, const std::string &username) {
    QString uploadDir = "uploads";
    if (!QDir().exists(uploadDir)) {
        QDir().mkpath(uploadDir);
    }

    QString savePath = uploadDir + "/" + QString::fromStdString(filename);
    QFile file(savePath);
    if (!file.open(QIODevice::WriteOnly)) {
        write_log("保存文件失败：" + savePath.toStdString());
        return false;
    }

    qint64 receivedBytes = 0;
    char buffer[4096];
    while (receivedBytes < filesize) {
        ssize_t len = read(sock, buffer, sizeof(buffer));
        if (len <= 0) break;
        file.write(buffer, len);
        receivedBytes += len;
    }

    file.close();
    if (receivedBytes == filesize) {
        Database::recordFileOwner(filename, username, filesize); // 记录文件归属
        write_log("成功接收并保存文件：" + filename + " 大小：" + std::to_string(filesize));
        return true;
    } else {
        write_log("接收失败，接收字节数：" + std::to_string(receivedBytes) + " / " + std::to_string(filesize));
        return false;
    }
}

void* handle_client(void* args) {
    QCoreApplication::instance();

    ThreadArgs* tArgs = (ThreadArgs*)args;
    int sock = tArgs->clientSock;
    sockaddr_in addr = tArgs->clientAddr;

    if (!Database::openConnectionForThread()) {
        write_log("线程数据库连接失败");
        close(sock);
        delete tArgs;
        return nullptr;
    }

    char clientIP[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &(addr.sin_addr), clientIP, INET_ADDRSTRLEN);
    int clientPort = ntohs(addr.sin_port);
    write_log("客户端连接：" + std::string(clientIP) + ":" + std::to_string(clientPort));

    std::string currentUser;

    while (true) {
        std::string cmdBuffer;
        char ch;
        while (read(sock, &ch, 1) == 1 && ch != '\n') {
            cmdBuffer += ch;
        }

        if (cmdBuffer.empty()) break;

        write_log("接收到命令: " + cmdBuffer);
        std::vector<std::string> tokens = split_command(cmdBuffer);

        if (tokens.size() == 4 && tokens[0] == "UPLOAD") {
            std::string username = tokens[1];
            std::string filename = tokens[2];
            std::string sizeStr = tokens[3];

            qint64 filesize = 0;
            try {
                filesize = std::stoll(sizeStr);
            } catch (const std::exception &e) {
                write_log("UPLOAD 命令解析失败（非法文件大小）: " + sizeStr + "，错误: " + e.what());
                std::string msg = "ERROR 文件大小格式非法\n";
                write(sock, msg.c_str(), msg.size());
                continue;
            }

            bool ok = handle_upload(sock, filename, filesize, username);
            if (ok) {
                std::string msg = "UPLOAD_SUCCESS\n";
                write(sock, msg.c_str(), msg.size());
                write_log("文件上传成功：" + filename + " 上传者：" + username);
            } else {
                std::string msg = "UPLOAD_FAIL\n";
                write(sock, msg.c_str(), msg.size());
            }
            continue;
        }



        // 修正点：DOWNLOAD filename username
        if (tokens.size() == 3 && tokens[0] == "DOWNLOAD") {
            std::string filename = tokens[1];
            std::string username = tokens[2];
            currentUser = username;

            QStringList allowedFiles = Database::listFilesByUser(currentUser);
            if (!allowedFiles.contains(QString::fromStdString(filename))) {
                std::string msg = "ERROR 无权限下载该文件\n";
                write(sock, msg.c_str(), msg.size());
                continue;
            }

            QString path = "uploads/" + QString::fromStdString(filename);
            QFile file(path);
            if (!file.exists()) {
                std::string msg = "ERROR 文件不存在\n";
                write(sock, msg.c_str(), msg.size());
                continue;
            }
            if (!file.open(QIODevice::ReadOnly)) {
                std::string msg = "ERROR 无法打开文件\n";
                write(sock, msg.c_str(), msg.size());
                continue;
            }

            QByteArray header = QString("OK %1\n").arg(file.size()).toUtf8();
            write(sock, header.data(), header.size());


            while (!file.atEnd()) {
                QByteArray chunk = file.read(4096);
                write(sock, chunk.data(), chunk.size());
            }

            file.close();
            write_log("成功发送文件：" + filename);
            continue;
        }

        if (tokens.size() == 2 && tokens[0] == "LIST_FILES") {
            std::string username = tokens[1];
            currentUser = username;

            QStringList files = Database::listFilesByUser(username);
            QString reply = files.join("\n") + "\n";
            write(sock, reply.toUtf8().constData(), reply.size());

            write_log("返回文件列表给用户：" + username);
            continue;
        }

        // DELETE 命令：DELETE filename username
        if (tokens.size() == 3 && tokens[0] == "DELETE") {
            std::string filename = tokens[1];
            std::string username = tokens[2];

            // 校验权限
            QStringList allowedFiles = Database::listFilesByUser(username);
            if (!allowedFiles.contains(QString::fromStdString(filename))) {
                std::string msg = "ERROR 无权限删除该文件\n";
                write(sock, msg.c_str(), msg.size());
                continue;
            }

            // 删除 uploads 中的实际文件
            QString filePath = "uploads/" + QString::fromStdString(filename);
            bool fileDeleted = QFile::remove(filePath);

            // 删除数据库记录
            bool dbDeleted = Database::deleteFileRecord(filename);

            if (fileDeleted && dbDeleted) {
                std::string msg = "DELETE_SUCCESS\n";
                write(sock, msg.c_str(), msg.size());
                write_log("用户 " + username + " 删除了文件：" + filename);
            } else {
                std::string msg = "DELETE_FAIL\n";
                write(sock, msg.c_str(), msg.size());
                write_log("用户 " + username + " 删除失败：" + filename);
            }
            continue;
        }
        if (tokens.size() == 2 && tokens[0] == "GET_LOG") {
            std::string username = tokens[1];
            currentUser = username;

            QFile logFile("server.log");
            if (!logFile.exists() || !logFile.open(QIODevice::ReadOnly)) {
                std::string msg = "ERROR 无法打开日志\n";
                write(sock, msg.c_str(), msg.size());
                continue;
            }

            QTextStream in(&logFile);
            QStringList filteredLogs;

            if (Database::isAdmin(username)) {
                while (!in.atEnd()) {
                    filteredLogs << in.readLine();
                }
                write_log("管理员查看了日志");
            } else {
                while (!in.atEnd()) {
                    QString line = in.readLine();
                    if (line.contains(QString::fromStdString(username))) {
                        filteredLogs << line;
                    }
                }
                write_log("用户查看了自己的日志：" + username);
            }

            QString content = filteredLogs.join("\n") + "\n";
            write(sock, content.toUtf8().constData(), content.toUtf8().size());
            logFile.close();
            continue;
        }


        std::string response;

        if (tokens.size() >= 3) {
            std::string action = tokens[0];
            std::string username = tokens[1];
            std::string password = tokens[2];

            if (action == "LOGIN") {
                if (Database::validateUser(username, password)) {
                    response = "LOGIN_SUCCESS\n";
                    write_log("用户登录成功：" + username);
                    currentUser = username;
                } else {
                    response = "LOGIN_FAIL\n";
                    write_log("用户登录失败：" + username);
                }
            } else if (action == "REGISTER") {
                if (Database::addUser(username, password)) {
                    response = "REGISTER_SUCCESS\n";
                    write_log("用户注册成功：" + username);
                } else {
                    response = "REGISTER_FAIL\n";
                    write_log("用户注册失败：" + username);
                }
            } else {
                response = "UNKNOWN_COMMAND\n";
                write_log("未知命令：" + action);
            }
        } else {
            response = "INVALID_FORMAT\n";
        }

        write(sock, response.c_str(), response.size());
    }

    write_log("客户端断开连接");

    QString connName = getThreadConnectionName();
    if (QSqlDatabase::contains(connName)) {
        QSqlDatabase::removeDatabase(connName);
        qDebug() << "已移除线程数据库连接：" << connName;
    }

    close(sock);
    delete tArgs;
    return nullptr;
}
